package br.ufmg.dcc.vod.remoteworkers.async;

import java.rmi.RemoteException;
import java.util.concurrent.TimeUnit;

import br.ufmg.dcc.vod.remoteworkers.AbstractTestCase;
import br.ufmg.dcc.vod.remoteworkers.CommandError;
import br.ufmg.dcc.vod.remoteworkers.util.RaceConditionCommand;

public class QueueBasedAsyncRemoteProcessorTest extends AbstractTestCase {

	public void testStartAndStop() throws RemoteException, InterruptedException {
		QueueBasedAsyncRemoteProcessor processor = new QueueBasedAsyncRemoteProcessor(PORT);
		processor.start();
		
		try {
		 processor.start();
		 fail();
		} catch (Exception e) { }
		
		processor.stop(false, Long.MAX_VALUE, TimeUnit.DAYS);
		
		try {
			 processor.start();
			 fail();
		} catch (Exception e) { }
		
		try {
			processor.stop(false, Long.MAX_VALUE, TimeUnit.DAYS);
			fail();
		} catch (Exception e) { }
	}
	
	public void testProcess() throws RemoteException, InterruptedException {
		
		QueueBasedAsyncRemoteProcessor processor = new QueueBasedAsyncRemoteProcessor(PORT);
		processor.start();

		MyCommandInterested interested = new MyCommandInterested();
		
		for (int i = 0; i <= 10; i++) {
			processor.process(new SimpleCommandRequest<Integer, Integer>(new RaceConditionCommand(), interested, ""));
		}
		
		//wait forever or until queue is empty!!!
		processor.stop(true, Long.MAX_VALUE, TimeUnit.DAYS);
		
		assertEquals(10, interested.expectedID);
	}
	
	public void testProcess2() throws RemoteException, InterruptedException {
		RaceConditionCommand.reset();
		
		QueueBasedAsyncRemoteProcessor processor = new QueueBasedAsyncRemoteProcessor(PORT);
		
		try {
			processor.process(null);
		} catch (NullPointerException e) {
		}
		
		processor.process(new SimpleCommandRequest<Integer, Integer>(new RaceConditionCommand(), new MyCommandInterested(), ""));
		processor.start();
		
		processor.stop(true, Long.MAX_VALUE, TimeUnit.DAYS);
		
		try {
			processor.process(new SimpleCommandRequest<Integer, Integer>(new RaceConditionCommand(), new MyCommandInterested(), ""));
			fail();
		} catch (Exception e) {}
	}
	
	private class MyCommandInterested implements CommandInterested<Integer, Integer> {

		private int expectedID = -1;

		@Override
		public void commandError(Integer i, CommandError e)	throws RemoteException {
			assertFalse(true);
		}

		@Override
		public void commandResponse(Integer i, Integer t) throws RemoteException {
			assertEquals(i.intValue(), t.intValue());
			assertEquals(++expectedID, i.intValue());
		}
		
	}
}
